package thread

import (
	"go_jvm/element"
	"math"
)

type Frame struct {
	// 链表
	before *Frame
	// 局部变量表
	LocalVarList LocalVars
	// 操作数栈
	OperandStack *OperandStack
}

func NewFrame(maxLocals uint64, maxStack uint64) *Frame {
	return &Frame{LocalVarList: NewLocalVars(maxLocals),
		OperandStack: NewOperandStack(maxStack),
	}
}

func NewLocalVars(maxLocals uint64) LocalVars {
	if maxLocals > 0 {
		return make([]Slot, maxLocals)
	}
	return nil
}

type Slot struct {
	num int32
	ref *element.Object
}

type LocalVars []Slot

func (self LocalVars) SetInt(index int, val int) {
	self[index].num = int32(val)
}
func (self LocalVars) GetInt(index int) int32 {
	return self[index].num
}

func (self LocalVars) SetFloat(index int, val float32) {
	self[index].num = int32(math.Float32bits(val))
}

func (self LocalVars) GetFloat(index int) float32 {
	return math.Float32frombits(uint32(self[index].num))
}

func (self LocalVars) setLong(index int, val int64) {
	self[index].num = int32(val)
	self[index+1].num = int32(val >> 32)
}

func (self LocalVars) GetLong(index int) int64 {
	low := self[index].num
	high := self[index+1].num
	return int64(high)<<32 | int64(low)
}

func (self LocalVars) SetDouble(index int, val float64) {
	bits := math.Float64bits(val)
	self.setLong(index, int64(bits))
}

func (self LocalVars) GetDouble(index int) float64 {
	bits := uint64(self.GetLong(index))
	return math.Float64frombits(bits)
}
